import java.awt.Component;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.plaf.ComboBoxUI;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeModel;
import javax.swing.DefaultCellEditor;
import javax.swing.GroupLayout;
import javax.swing.GroupLayout.Alignment;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JMenu;
import javax.swing.JOptionPane;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Vector;
import javax.swing.JTree;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.JScrollPane;
import javax.swing.LayoutStyle.ComponentPlacement;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import DataBaseManager.Data;
import DataBaseManager.DataBase;
import DataBaseManager.Field;
import DataBaseManager.Row;
import DataBaseManager.Table;
import DataType.MyDataType;
import DataType.MyDataType.MY_TYPE;
import javax.swing.JLabel;
import java.awt.event.*;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import javax.swing.event.ChangeListener;
import javax.swing.event.ChangeEvent;
import javax.swing.filechooser.FileFilter;
import javax.swing.filechooser.FileNameExtensionFilter;
import javax.swing.JButton;
import javax.swing.JTextField;

public class Server extends JFrame {

	// file/folder opener
	JFileChooser folderChooser = new JFileChooser();
	JFileChooser fileChooser = new JFileChooser();

	// My parameter
	private JLabel lblClosed;
	private ServerSocket socket;

	ColorRenderer cr;
	private JButton btnDeleteRow;
	private JMenu mnTable;
	private JMenu mnDatabase;
	private JButton btnOpenServer;
	private Query query;
	private String DATABASENAME = "No database load";
	private String FILEPATH;
	private TreeModel _TreeModel = null;
	private String[] FIELDTYPES = new String[] { "String", "Integer" };

	private FileInputStream _inputStream;
	private FileOutputStream _outputSteam;
	private ObjectOutputStream _objOutputStream;

	private boolean isConnected;

	private DataBase _MyDatabase = null;

	private DefaultTableModel _TableDesignModel = new DefaultTableModel(
			new Object[][] {,}, new String[] { "Field", "Type", "Primary Key",
					"Allow null" }) {
		/**
						 * 
						 */
		private static final long serialVersionUID = 1L;
		@SuppressWarnings("rawtypes")
		Class[] columnTypes = new Class[] { String.class, ComboBoxUI.class,
				Boolean.class, Boolean.class };

		@SuppressWarnings({ "rawtypes", "unchecked" })
		public Class getColumnClass(int columnIndex) {
			return columnTypes[columnIndex];
		}
	};

	private DefaultTableModel _TableViewModel = new DefaultTableModel();

	private int _FocusingTable = 0;

	// my class
	public class MyComboBoxEditor extends DefaultCellEditor {
		/**
		 * 
		 */
		private static final long serialVersionUID = 1L;

		public MyComboBoxEditor(String[] items) {
			super(new JComboBox(items));
		}
	}

	public class MyComboBoxRenderer extends JComboBox implements
			TableCellRenderer {
		/**
		 * 
		 */
		private static final long serialVersionUID = 1L;

		public MyComboBoxRenderer(String[] items) {
			super(items);
		}

		public Component getTableCellRendererComponent(JTable table,
				Object value, boolean isSelected, boolean hasFocus, int row,
				int column) {
			if (isSelected) {
				setForeground(table.getSelectionForeground());
				super.setBackground(table.getSelectionBackground());
			} else {
				setForeground(table.getForeground());
				setBackground(table.getBackground());
			}

			// Select the current value
			setSelectedItem(value);
			return this;
		}
	}

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private JPanel contentPane;
	private JTable tableView;
	private JTable tableDesign;
	private JTree tree;
	private JScrollPane scrollPane;
	private JLabel labelFocus;
	private JTextField textFieldPort;

	/**
	 * Launch the application.
	 */
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					Server frame = new Server();

					frame.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	/**
	 * Create the frame.
	 */

	public Server() {
		setResizable(false);
		isConnected = false;
		setTitle("Server");

		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setBounds(100, 100, 905, 566);

		JMenuBar menuBar = new JMenuBar();
		setJMenuBar(menuBar);

		JMenu mnSystem = new JMenu("System");
		menuBar.add(mnSystem);

		JMenuItem mntmSave = new JMenuItem("Save");
		mntmSave.addMouseListener(new MouseAdapter() {
			@Override
			public void mousePressed(MouseEvent e) {
				SaveDatabaseToFile();
			}
		});
		mnSystem.add(mntmSave);

		JMenuItem mntmExit = new JMenuItem("Exit");
		mntmExit.addMouseListener(new MouseAdapter() {
			@Override
			public void mousePressed(MouseEvent e) {
				if (_MyDatabase != null) {
					int result = JOptionPane.showConfirmDialog(new Server(),
							"Do you want to save before exit?", "Warning",
							JOptionPane.YES_NO_CANCEL_OPTION);
					switch (result) {
					case JOptionPane.YES_OPTION: {
						// save lai roi thoat
						SaveDatabaseToFile();
						System.exit(DO_NOTHING_ON_CLOSE);
						break;
					}

					case JOptionPane.NO_OPTION: {
						// thoat luon khoi save
						System.exit(DO_NOTHING_ON_CLOSE);
						break;
					}

					default:
						break;
					}
				} else {
					System.exit(DO_NOTHING_ON_CLOSE);
				}
			}
		});
		mnSystem.add(mntmExit);

		mnDatabase = new JMenu("Database");
		menuBar.add(mnDatabase);

		JMenuItem mntmNewDatabase = new JMenuItem("New database");
		mntmNewDatabase.addMouseListener(new MouseAdapter() {
			@Override
			public void mousePressed(MouseEvent arg0) {
				CreateNewDatabase();
			}
		});
		mnDatabase.add(mntmNewDatabase);

		JMenuItem mntmLoadDatabase = new JMenuItem("Load database");
		mntmLoadDatabase.addMouseListener(new MouseAdapter() {
			@Override
			public void mousePressed(MouseEvent e) {
				LoadDatabaseFromFile();
			}
		});
		mnDatabase.add(mntmLoadDatabase);

		JMenuItem mntmDeleteDatabse = new JMenuItem("Delete database");
		mntmDeleteDatabse.addMouseListener(new MouseAdapter() {
			@Override
			public void mousePressed(MouseEvent arg0) {
				DelDatabase();
			}
		});
		mnDatabase.add(mntmDeleteDatabse);

		JMenuItem mntmCloseDatabase = new JMenuItem("Close database");
		mntmCloseDatabase.addMouseListener(new MouseAdapter() {
			@Override
			public void mousePressed(MouseEvent arg0) {
				CloseDatabase();
			}
		});
		mnDatabase.add(mntmCloseDatabase);

		mnTable = new JMenu("Table");
		menuBar.add(mnTable);

		JMenuItem mntmAddTable = new JMenuItem("Add table");
		mntmAddTable.addMouseListener(new MouseAdapter() {
			@Override
			public void mousePressed(MouseEvent arg0) {
				AddNewTable();
			}
		});
		mnTable.add(mntmAddTable);

		JMenuItem mntmDeleteTable = new JMenuItem("Delete table");
		mntmDeleteTable.addMouseListener(new MouseAdapter() {
			@Override
			public void mousePressed(MouseEvent arg0) {
				if (_MyDatabase != null) {
					DeleteTable(labelFocus.getText());
				} else {
					JOptionPane.showMessageDialog(new Server(), "No database.",
							"Error", JOptionPane.ERROR_MESSAGE);
				}
			}
		});
		mnTable.add(mntmDeleteTable);
		contentPane = new JPanel();
		contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
		setContentPane(contentPane);

		JPanel panel = new JPanel();

		JPanel panel_1 = new JPanel();

		JLabel lblFocus = new JLabel("Focus:");

		labelFocus = new JLabel("Focus item");

		btnDeleteRow = new JButton("Delete row");
		btnDeleteRow.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent arg0) {
				if (!isConnected)
					DeleteRow();
			}
		});

		JLabel lblPort = new JLabel("Port:");

		textFieldPort = new JTextField();
		textFieldPort.setText("8888");
		textFieldPort.setColumns(10);

		btnOpenServer = new JButton("Open server");
		btnOpenServer.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent arg0) {
				if (isConnected) {
					setConnect(false);
					lblClosed.setText("Closed");
					return;
				}
				setConnect(true);
				int port = -1;

				try {
					port = Integer.parseInt(textFieldPort.getText());
					if (port > 0 && port < 10000) {
						try {
							socket = new ServerSocket(port);
							textFieldPort.setEditable(false);
						} catch (IOException e) {
							e.printStackTrace();
						}
						listen();
					} else
						JOptionPane.showMessageDialog(contentPane,
								"Port must be beween 1 ~ 9999");
				} catch (NumberFormatException nfe) {
					JOptionPane.showMessageDialog(contentPane,
							"Port must be a number");
				}
			}
		});

		JLabel lblStatus = new JLabel("Status:");

		lblClosed = new JLabel("Closed");

		GroupLayout gl_contentPane = new GroupLayout(contentPane);
		gl_contentPane
				.setHorizontalGroup(gl_contentPane
						.createParallelGroup(Alignment.LEADING)
						.addGroup(
								gl_contentPane
										.createSequentialGroup()
										.addGroup(
												gl_contentPane
														.createParallelGroup(
																Alignment.TRAILING,
																false)
														.addGroup(
																gl_contentPane
																		.createSequentialGroup()
																		.addComponent(
																				lblFocus)
																		.addPreferredGap(
																				ComponentPlacement.RELATED)
																		.addComponent(
																				labelFocus,
																				GroupLayout.DEFAULT_SIZE,
																				GroupLayout.DEFAULT_SIZE,
																				Short.MAX_VALUE))
														.addComponent(
																panel,
																Alignment.LEADING,
																GroupLayout.PREFERRED_SIZE,
																196,
																GroupLayout.PREFERRED_SIZE))
										.addPreferredGap(
												ComponentPlacement.RELATED)
										.addGroup(
												gl_contentPane
														.createParallelGroup(
																Alignment.LEADING)
														.addComponent(
																panel_1,
																GroupLayout.DEFAULT_SIZE,
																677,
																Short.MAX_VALUE)
														.addGroup(
																gl_contentPane
																		.createSequentialGroup()
																		.addComponent(
																				btnDeleteRow)
																		.addContainerGap())))
						.addGroup(
								gl_contentPane
										.createSequentialGroup()
										.addComponent(lblPort)
										.addPreferredGap(
												ComponentPlacement.RELATED)
										.addComponent(textFieldPort,
												GroupLayout.PREFERRED_SIZE, 32,
												GroupLayout.PREFERRED_SIZE)
										.addPreferredGap(
												ComponentPlacement.RELATED)
										.addComponent(btnOpenServer)
										.addPreferredGap(
												ComponentPlacement.RELATED)
										.addComponent(lblStatus)
										.addPreferredGap(
												ComponentPlacement.RELATED)
										.addComponent(lblClosed).addGap(635)));
		gl_contentPane
				.setVerticalGroup(gl_contentPane
						.createParallelGroup(Alignment.TRAILING)
						.addGroup(
								gl_contentPane
										.createSequentialGroup()
										.addGroup(
												gl_contentPane
														.createParallelGroup(
																Alignment.BASELINE)
														.addComponent(lblPort)
														.addComponent(
																textFieldPort,
																GroupLayout.PREFERRED_SIZE,
																GroupLayout.DEFAULT_SIZE,
																GroupLayout.PREFERRED_SIZE)
														.addComponent(
																btnOpenServer)
														.addComponent(lblStatus)
														.addComponent(lblClosed))
										.addPreferredGap(
												ComponentPlacement.RELATED,
												GroupLayout.DEFAULT_SIZE,
												Short.MAX_VALUE)
										.addGroup(
												gl_contentPane
														.createParallelGroup(
																Alignment.BASELINE)
														.addComponent(lblFocus)
														.addComponent(
																labelFocus)
														.addComponent(
																btnDeleteRow))
										.addPreferredGap(
												ComponentPlacement.RELATED)
										.addGroup(
												gl_contentPane
														.createParallelGroup(
																Alignment.LEADING,
																false)
														.addComponent(
																panel,
																GroupLayout.DEFAULT_SIZE,
																GroupLayout.DEFAULT_SIZE,
																Short.MAX_VALUE)
														.addComponent(
																panel_1,
																GroupLayout.DEFAULT_SIZE,
																421,
																Short.MAX_VALUE))));

		JTabbedPane tabbedPane = new JTabbedPane(JTabbedPane.TOP);
		tabbedPane.addChangeListener(new ChangeListener() {
			public void stateChanged(ChangeEvent arg0) {
				JTabbedPane pane = (JTabbedPane) arg0.getSource();
				_FocusingTable = pane.getSelectedIndex();
				if (_FocusingTable == 0)
					UpdateViewTab();
				else if (_FocusingTable == 1)
					UpdateDesignTab();
			}
		});

		JScrollPane scrollPane_1 = new JScrollPane();

		tabbedPane.addTab("View", null, scrollPane_1, null);

		tableView = new JTable();
		tableView.setCellSelectionEnabled(true);
		scrollPane_1.setViewportView(tableView);
		GroupLayout gl_panel_1 = new GroupLayout(panel_1);
		gl_panel_1.setHorizontalGroup(gl_panel_1.createParallelGroup(
				Alignment.LEADING).addComponent(tabbedPane,
				GroupLayout.PREFERRED_SIZE, 673, GroupLayout.PREFERRED_SIZE));
		gl_panel_1.setVerticalGroup(gl_panel_1.createParallelGroup(
				Alignment.LEADING).addComponent(tabbedPane,
				GroupLayout.PREFERRED_SIZE, 421, GroupLayout.PREFERRED_SIZE));

		JScrollPane scrollPane_2 = new JScrollPane();

		tabbedPane.addTab("Design", null, scrollPane_2, null);

		tableDesign = new JTable();
		tableDesign.setCellSelectionEnabled(true);
		tableDesign.setModel(_TableDesignModel);

		TableColumn col = tableDesign.getColumnModel().getColumn(1);

		col.setCellEditor(new MyComboBoxEditor(FIELDTYPES));
		col.setCellRenderer(new MyComboBoxRenderer(FIELDTYPES));

		scrollPane_2.setViewportView(tableDesign);
		panel_1.setLayout(gl_panel_1);

		DefaultMutableTreeNode root = new DefaultMutableTreeNode(DATABASENAME);
		_TreeModel = new DefaultTreeModel(root);

		scrollPane = new JScrollPane();
		GroupLayout gl_panel = new GroupLayout(panel);
		gl_panel.setHorizontalGroup(gl_panel.createParallelGroup(
				Alignment.LEADING).addComponent(scrollPane,
				GroupLayout.DEFAULT_SIZE, 196, Short.MAX_VALUE));
		gl_panel.setVerticalGroup(gl_panel.createParallelGroup(
				Alignment.LEADING).addComponent(scrollPane,
				GroupLayout.DEFAULT_SIZE, 421, Short.MAX_VALUE));

		tree = new JTree(root);
		tree.addMouseListener(new MouseAdapter() {
			@Override
			public void mousePressed(MouseEvent arg0) {
				String text = "";
				if (tree.getSelectionPath() != null)
					text = tree.getSelectionPath().getLastPathComponent()
							.toString();
				labelFocus.setText(text);
				UpdateViewTab();
				UpdateDesignTab();
			}
		});

		scrollPane.setViewportView(tree);

		tree.setModel(_TreeModel);

		tree.setShowsRootHandles(true);
		panel.setLayout(gl_panel);
		contentPane.setLayout(gl_contentPane);

		SetDesignListener();

		setViewListener();

		this.addWindowListener(new WindowAdapter() {

			public void windowClosing(WindowEvent e) {
				try {
					isConnected = false;
					if (_MyDatabase != null) {
						int result = JOptionPane.showConfirmDialog(
								new Server(),
								"Do you want to save before exit?", "Warning",
								JOptionPane.YES_NO_OPTION);
						switch (result) {
						case JOptionPane.YES_OPTION: {
							// save lai roi thoat
							SaveDatabaseToFile();
							System.exit(DO_NOTHING_ON_CLOSE);
							break;
						}

						case JOptionPane.NO_OPTION: {
							// thoat luon khoi save
							System.exit(DO_NOTHING_ON_CLOSE);
							break;
						}

						default:
							break;
						}
					} else {
						System.exit(DO_NOTHING_ON_CLOSE);
					}
				} catch (Exception ex) {
				}
				// System.exit(0);
			}
		});

		// file opener
		FileFilter filter = new FileNameExtensionFilter("Database file",
				"dtbjv");
		fileChooser.setCurrentDirectory(new java.io.File("."));
		fileChooser.setDialogTitle("Select file");
		fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
		fileChooser.setAcceptAllFileFilterUsed(false);
		fileChooser.addChoosableFileFilter(filter);

		// folder opener
		folderChooser.setCurrentDirectory(new java.io.File("."));
		folderChooser.setDialogTitle("Select Directory");
		folderChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
		folderChooser.setAcceptAllFileFilterUsed(false);
	}

	private void setConnect(boolean flag) {
		if (flag) {
			btnOpenServer.setText("Close sever");

		} else {
			btnOpenServer.setText("Open sever");
		}
		// btnOpenServer.setEnabled(!flag);
		tableView.setEnabled(!flag);
		tableDesign.setEnabled(!flag);
		mnDatabase.setEnabled(!flag);
		mnTable.setEnabled(!flag);
		btnDeleteRow.setEnabled(!flag);
		isConnected = flag;
	}

	boolean isPressed = false;

	private void setViewListener() {
		// isPressed = true;
		tableView.addKeyListener(new KeyListener() {

			public void keyPressed(KeyEvent e) {
				if (e.getKeyCode() == KeyEvent.VK_ENTER) {
					int nRow = tableView.getSelectedRow();
					int n = tableView.getRowCount();
					if (nRow == n - 1) {
						_TableViewModel.insertRow(
								_TableViewModel.getRowCount(),
								new Vector<String>());
						isPressed = true;
					}
				}
			}

			public void keyReleased(KeyEvent e) {
				// isPressed = false;
				if (e.getKeyCode() == KeyEvent.VK_ENTER) {
					Table selectedTable = _MyDatabase.getTable(labelFocus
							.getText());
					int nRow = tableView.getSelectedRow() - 1;
					int n = tableView.getRowCount() - 1;

					if (isPressed) {
						isPressed = false;
						Row row = new Row();
						for (int i = 0; i < tableView.getColumnCount(); i++) {
							MyDataType adder = new MyDataType();

							String val = "";
							if (tableView.getValueAt(nRow, i) != null)
								val = tableView.getValueAt(nRow, i).toString();
							adder.setValue(val);
							adder = adder.setType(selectedTable.getFields()
									.get(i).getType());

							row.add(adder);
						}

						int error = selectedTable.insertData(row);
						if (error != -1) {
							JOptionPane.showMessageDialog(
									contentPane,
									"Invalid data : \'"
											+ _TableViewModel
													.getColumnName(error)
											+ "\'");
							cr.setColumn(error);
							_TableViewModel.removeRow(n);
						} else {
							cr.setColumn(-1);
							for (int i = 0; i < tableView.getColumnCount(); i++) {
								tableView.setValueAt(
										selectedTable.getValue(i, nRow)
												.toString(), nRow, i);
							}
						}
					}
				}
			}

			public void keyTyped(KeyEvent e) {
			}
		});
		_TableViewModel.addTableModelListener(new TableModelListener() {

			@Override
			public void tableChanged(TableModelEvent arg0) {

				int nRow = arg0.getLastRow();
				int nCol = arg0.getColumn();
				if (isEditedBySystem) {
					isEditedBySystem = false;
					return;
				} else if (nCol >= 0 && nRow >= 0 && !isPressed
						&& (nRow != _TableViewModel.getRowCount() - 1)) {
					Table selectedTable = _MyDatabase.getTable(labelFocus
							.getText());
					if (selectedTable != null) {
						Data dataInTable = selectedTable.getData();
						if (dataInTable != null
								&& dataInTable.getRows() != null) {
							if (dataInTable.getRowCount() < nRow + 1) {
								dataInTable.insert(new Row(selectedTable
										.getFields().size()));
							}

							MyDataType adder = new MyDataType();

							adder.setValue(tableView.getValueAt(nRow, nCol)
									.toString());
							adder = adder.setType(selectedTable.getFields()
									.get(nCol).getType());

							if (!selectedTable.setData(nRow, nCol, adder)) {
								JOptionPane.showMessageDialog(contentPane,
										"Invalid Data");
							}
							isEditedBySystem = true;
							tableView.setValueAt(
									selectedTable.getValue(nCol, nRow)
											.toString(), nRow, nCol);
						}
					}
				}

			}
		});

	}

	private boolean isEditedBySystem = false;

	private void SetDesignListener() {
		_TableDesignModel.addTableModelListener(new TableModelListener() {

			@Override
			public void tableChanged(TableModelEvent arg0) {
				if (isEditedBySystem) {
					isEditedBySystem = false;
					return;
				}
				int nRow = arg0.getLastRow();
				int nCol = arg0.getColumn();
				if (nCol >= 0 && nRow >= 0) {
					Table selectedTable = _MyDatabase.getTable(labelFocus
							.getText());
					if (selectedTable != null) {
						ArrayList<Field> listfield = selectedTable.getFields();
						String newValue = _TableDesignModel.getValueAt(nRow,
								nCol).toString();
						switch (nCol) {
						case 0: {
							String newFieldName = newValue;
							if (nRow == _TableDesignModel.getRowCount() - 1) {
								if (newFieldName.length() == 0)
									return;
								if (!CheckEngine.IsNoSpecialChar(newFieldName)) {
									JOptionPane.showMessageDialog(contentPane,
											"Invalid field name !");
									isEditedBySystem = true;
									_TableDesignModel
											.setValueAt("", nRow, nCol);
									return;
								}
								for (int i = 0; i < listfield.size(); i++) {
									if (i != nRow
											&& newFieldName
													.equalsIgnoreCase(listfield
															.get(i).getName())) {
										JOptionPane.showMessageDialog(
												contentPane,
												"Duplicated field name !");
										isEditedBySystem = true;
										_TableDesignModel.setValueAt("", nRow,
												nCol);
										return;
									}
								}
								listfield.add(new Field(newFieldName,
										MY_TYPE.MY_STRING));
								isEditedBySystem = true;
								_TableDesignModel.setValueAt("String", nRow, 1);
								isEditedBySystem = true;
								_TableDesignModel.setValueAt(true, nRow, 3);
								isEditedBySystem = true;
								_TableDesignModel.insertRow(
										_TableDesignModel.getRowCount(),
										new Vector<String>());
								selectedTable.addDataColumn();

							} else {
								String lastFieldName = listfield.get(nRow)
										.getName();

								if (!CheckEngine.IsNoSpecialChar(newFieldName)) {
									JOptionPane.showMessageDialog(contentPane,
											"Invalid field name !");
									isEditedBySystem = true;
									_TableDesignModel.setValueAt(lastFieldName,
											nRow, nCol);
									return;
								}
								for (int i = 0; i < listfield.size(); i++) {
									if (i != nRow
											&& newFieldName
													.equalsIgnoreCase(listfield
															.get(i).getName())) {
										JOptionPane.showMessageDialog(
												contentPane,
												"Duplicated field name !");
										isEditedBySystem = true;
										_TableDesignModel.setValueAt(
												lastFieldName, nRow, nCol);
										return;
									}
								}
								listfield.get(nRow).setName(newFieldName);
							}
							break;

						}
						case 1: {
							if (nRow == _TableDesignModel.getRowCount() - 1) {
								isEditedBySystem = true;
								_TableDesignModel.setValueAt(null, nRow, nCol);
								return;
							}

							if (newValue.compareTo("String") == 0) {

								selectedTable.setDataType(nRow,
										MY_TYPE.MY_STRING);

							} else {
								if (selectedTable.checkConvertData(nRow,
										MY_TYPE.MY_NUMBERIC)) {
									selectedTable.setDataType(nRow,
											MY_TYPE.MY_NUMBERIC);
								} else {
									int i = JOptionPane.showConfirmDialog(
											contentPane,
											"Convert from STRING to INTERGER may cause lost data\n"
													+ "Process this ?",
											"Warning!",
											JOptionPane.YES_NO_OPTION);
									if (i == 0) {
										selectedTable.setDataType(nRow,
												MY_TYPE.MY_NUMBERIC);
									} else {
										String type = "";
										if (listfield.get(i).getType() == MY_TYPE.MY_NUMBERIC)
											type = "Integer";
										else
											type = "String";
										isEditedBySystem = true;
										_TableDesignModel.setValueAt(type,
												nRow, nCol);
									}
								}

							}

							break;
						}
						case 2: {
							if (nRow == _TableDesignModel.getRowCount() - 1) {
								isEditedBySystem = true;
								_TableDesignModel.setValueAt(false, nRow, nCol);
								return;
							}

							Boolean isPK = Boolean.valueOf(newValue);
							if (isPK) {
								if (!selectedTable.setPrivateKey(nRow)) {
									JOptionPane
											.showMessageDialog(
													contentPane,
													"Can not set \'"
															+ listfield.get(
																	nRow)
																	.getName()
															+ "\' as private key : Duplicated or null data");
								}
								UpdateDesignTab();
							} else {
								listfield.get(nRow).setPrivateKey(isPK);
								isEditedBySystem = true;
								_TableDesignModel.setValueAt(listfield
										.get(nRow).AllowNull(), nRow, 3);
							}

							break;
						}
						case 3: {
							if (nRow == _TableDesignModel.getRowCount() - 1) {
								isEditedBySystem = true;
								_TableDesignModel.setValueAt(false, nRow, nCol);
								return;
							}

							Boolean alowNull = Boolean.valueOf(newValue);
							if (!selectedTable.setAlowNull(nRow, alowNull)) {
								JOptionPane
										.showMessageDialog(
												contentPane,
												"Can not set \'"
														+ listfield.get(nRow)
																.getName()
														+ "\' as NOT allow null : Null data");
								isEditedBySystem = true;
								_TableDesignModel.setValueAt(listfield
										.get(nRow).AllowNull(), nRow, nCol);
							}
							isEditedBySystem = true;
							_TableDesignModel.setValueAt(listfield.get(nRow)
									.PrivateKey(), nRow, 2);
							break;
						}

						default:
							break;
						}

					}
				}

			}
		});
	}

	private DefaultMutableTreeNode processHierarchy(Object[] hierarchy) {
		DefaultMutableTreeNode node = new DefaultMutableTreeNode(hierarchy[0]);
		DefaultMutableTreeNode child;
		for (int i = 1; i < hierarchy.length; i++) {
			Object nodeSpecifier = hierarchy[i];
			if (nodeSpecifier instanceof Object[]) // Is node with children
				child = processHierarchy((Object[]) nodeSpecifier);
			else
				child = new DefaultMutableTreeNode(nodeSpecifier); // Is Leaf
			node.add(child);
		}
		return (node);
	}

	private void CloseDatabase() {
		if (this._MyDatabase == null) {
			JOptionPane.showMessageDialog(new Server(), "No database load.",
					"Error", JOptionPane.OK_OPTION);
		} else {
			int result = JOptionPane.showConfirmDialog(new Server(),
					"Do you want to save before close database?", "Warning",
					JOptionPane.YES_NO_CANCEL_OPTION);
			switch (result) {
			case JOptionPane.YES_OPTION: {
				// save lai roi thoat
				this.SaveDatabaseToFile();
				SetTreeToDefault();
				this._MyDatabase = null;
				this.FILEPATH = null;
				this.labelFocus.setText("No database load");
				UpdateDesignTab();
				UpdateViewTab();
				break;
			}

			case JOptionPane.NO_OPTION: {
				// thoat luon khoi save
				SetTreeToDefault();
				this._MyDatabase = null;
				this.FILEPATH = null;
				this.labelFocus.setText("No database load");
				UpdateDesignTab();
				UpdateViewTab();
				break;
			}

			default:
				break;
			}
		}
	}

	private void SetTreeToDefault() {
		DefaultMutableTreeNode root = processHierarchy(new String[] { DATABASENAME });
		_TreeModel = new DefaultTreeModel(root);

		tree.setModel(_TreeModel);
		scrollPane.setViewportView(tree);
	}

	private void CreateNewDatabase() {
		if (folderChooser.showSaveDialog(new Server()) == JFileChooser.APPROVE_OPTION) {
			String databasename = JOptionPane.showInputDialog(new Server(),
					"Database name: ", "Infomation",
					JOptionPane.OK_CANCEL_OPTION);
			if (null != databasename) {
				if (CheckEngine.IsNoSpecialChar(databasename)) {
					this._MyDatabase = new DataBase(databasename);
					File direc = folderChooser.getSelectedFile();
					FILEPATH = direc.getPath() + "\\" + _MyDatabase.getName()
							+ ".dtbjv";
					//this.DATABASENAME = _MyDatabase.getName();
					CreateFileDatabase();
					UpdateGUI();
				} else {
					JOptionPane.showMessageDialog(new Server(),
							"Database name is invalid.", "Error",
							JOptionPane.OK_OPTION);
				}
			}
		}
	}

	private void CreateFileDatabase() {
		File a = new File(FILEPATH);
		try {
			a.createNewFile();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	private void UpdateGUI() {
		if (_MyDatabase != null) {
			String[] listElement = CreateListForTree();
			DefaultMutableTreeNode root = processHierarchy(listElement);
			_TreeModel = new DefaultTreeModel(root);

			tree.setModel(_TreeModel);
			scrollPane.setViewportView(tree);
		} else {
			SetTreeToDefault();
		}
	}

	private String[] CreateListForTree() {
		String[] result = null;
		ArrayList<String> temp = new ArrayList<String>();
		temp.add(_MyDatabase.getName());
		ArrayList<Table> tables = _MyDatabase.getListTables();
		if (tables != null) {
			for (int i = 0; i < tables.size(); i++) {
				temp.add(tables.get(i).getName());
			}
		}
		result = new String[temp.size()];
		for (int i = 0; i < temp.size(); i++) {
			result[i] = temp.get(i);
		}
		return result;
	}

	private void AddNewTable() {
		if (_MyDatabase == null) {
			JOptionPane
					.showMessageDialog(new Server(),
							"No database to add table.", "Error",
							JOptionPane.OK_OPTION);
		} else {
			String tablename = JOptionPane.showInputDialog(new Server(),
					"Table name: ", "Infomation", JOptionPane.OK_CANCEL_OPTION);
			if (null != tablename) {
				if (CheckEngine.IsNoSpecialChar(tablename)) {
					if (!tablename.equals(_MyDatabase.getName())) {
						if (!this._MyDatabase.addTable(new Table(tablename))) {
							JOptionPane.showMessageDialog(new Server(),
									"Table name already exists.", "Error",
									JOptionPane.OK_OPTION);
						}
						UpdateGUI();
					} else {
						JOptionPane
								.showMessageDialog(
										new Server(),
										"Table name must be different with database name.",
										"Error", JOptionPane.OK_OPTION);
					}

				} else {
					JOptionPane.showMessageDialog(new Server(),
							"Table name is invalid.", "Error",
							JOptionPane.OK_OPTION);
				}
			}
		}
	}

	private void UpdateViewTab() {

		_TableViewModel = new DefaultTableModel();

		ArrayList<String> columname = new ArrayList<String>();

		if (this._MyDatabase != null) {
			String name = labelFocus.getText();
			Table table = this._MyDatabase.getTable(name);
			if (table != null) {
				ArrayList<Field> ListField = table.getFields();
				if (ListField != null) {
					for (int i = 0; i < ListField.size(); i++) {
						columname.add(ListField.get(i).getName());
					}

					String[] ListName = ListToArr(columname);

					this._TableViewModel = new DefaultTableModel(ListName, 0);

					Data selectedData = table.getData();
					for (int i = 0; i < selectedData.getRowCount(); i++) {
						_TableViewModel.addRow(selectedData.getValueOfRow(i));
					}
					this._TableViewModel.insertRow(
							this._TableViewModel.getRowCount(),
							new Vector<String>());
					this.tableView.setModel(_TableViewModel);
					this.setViewListener();
				}
			} else {
				ResetViewToNullState();
			}
			cr = new ColorRenderer(-1);

			for (int i = 0; i < tableView.getColumnCount(); i++)
				tableView.getColumn(tableView.getColumnName(i))
						.setCellRenderer(cr);
		} else {
			ResetViewToNullState();
		}

	}

	private void ResetViewToNullState() {
		_TableViewModel = new DefaultTableModel(new Object[][] {,},
				new String[] {});
		if (tableView == null) {
			tableView = new JTable();
			tableView.setCellSelectionEnabled(true);
		}
		this.tableView.setModel(_TableViewModel);
		setViewListener();
	}

	private void UpdateDesignTab() {
		_TableDesignModel = new DefaultTableModel(new Object[][] {,},
				new String[] { "Field", "Type", "Primary Key", "Allow null" }) {
			private static final long serialVersionUID = 1L;
			@SuppressWarnings("rawtypes")
			Class[] columnTypes = new Class[] { String.class, ComboBoxUI.class,
					Boolean.class, Boolean.class };

			@SuppressWarnings({ "rawtypes", "unchecked" })
			public Class getColumnClass(int columnIndex) {
				return columnTypes[columnIndex];
			}
		};

		if (this._MyDatabase != null) {
			String name = labelFocus.getText();
			Table table = this._MyDatabase.getTable(name);
			if (table != null) {
				ArrayList<Field> ListField = table.getFields();
				if (ListField != null) {
					for (int i = 0; i < ListField.size(); i++) {
						String type = "";
						if (ListField.get(i).getType() == MY_TYPE.MY_NUMBERIC)
							type = "Integer";
						else
							type = "String";
						this._TableDesignModel.addRow(new Object[] {
								ListField.get(i).getName(), type,
								ListField.get(i).PrivateKey(),
								ListField.get(i).AllowNull() });

					}
					_TableDesignModel.insertRow(
							_TableDesignModel.getRowCount(),
							new Vector<String>());
					this.tableDesign.setModel(_TableDesignModel);
					TableColumn col = tableDesign.getColumnModel().getColumn(1);

					col.setCellEditor(new MyComboBoxEditor(FIELDTYPES));
					col.setCellRenderer(new MyComboBoxRenderer(FIELDTYPES));
					SetDesignListener();
				}
			} else {
				ResetDesignToNullState();
			}
		} else {
			ResetDesignToNullState();

		}
	}

	private void ResetDesignToNullState() {
		_TableDesignModel = new DefaultTableModel(new Object[][] {,},
				new String[] {});
		this.tableDesign.setModel(_TableDesignModel);
		SetDesignListener();
	}

	private String[] ListToArr(ArrayList<String> input) {
		String[] result = new String[input.size()];

		for (int i = 0; i < input.size(); i++) {
			result[i] = input.get(i);
		}

		return result;
	}


	private void DeleteRow() {

		switch (_FocusingTable) {

		case 0: {
			if (tableView.getSelectedRow() < 0
					|| tableView.getSelectedRow() >= tableView.getRowCount() - 1) {
				JOptionPane.showMessageDialog(new Server(),
						"Select row to delete.");
				return;
			}
			_MyDatabase.getTable(labelFocus.getText()).getData()
					.DeleteRow(tableView.getSelectedRow());
			this._TableViewModel.removeRow(tableView.getSelectedRow());
		}
			break;

		case 1: {
			if (tableDesign.getSelectedRow() < 0
					|| tableDesign.getSelectedRow() >= tableDesign
							.getRowCount() - 1) {
				JOptionPane.showMessageDialog(new Server(),
						"Select row to delete.");
				return;
			}
			_MyDatabase.getTable(labelFocus.getText()).getFields()
					.remove(tableDesign.getSelectedRow());
			for (int i = 0; i < _MyDatabase.getTable(labelFocus.getText())
					.getData().getRowCount(); i++) {
				_MyDatabase.getTable(labelFocus.getText()).getData().getRows()
						.get(i).DeleteColum(tableDesign.getSelectedRow());
			}
			_TableDesignModel.removeRow(tableDesign.getSelectedRow());

			break;
		}

		default:
			JOptionPane
					.showMessageDialog(new Server(), "Select row to delete.");
			break;
		}
	}

	private void listen() {

		Thread playThread = new Thread() {
			@Override
			public void run() {
				Socket client;
				BufferedReader br;
				lblClosed.setText("Opened");
				ObjectOutputStream oout;
				try {

					client = socket.accept();

					InputStream is = client.getInputStream();
					br = new BufferedReader(new InputStreamReader(is));

					oout = new ObjectOutputStream(client.getOutputStream());
					// lblClosed.setText("Conected");
				} catch (IOException e1) {
					// e1.printStackTrace();
					return;
				}
				if (isConnected)
					listen();

				while (true) {

					//
					try {
						String sqlString = br.readLine();
						if (!isConnected) {
							oout.writeObject(DTO.CreateDTO("Disconnected!"));
							oout.close();
							client.close();
							break;
						}
						if (query == null) {
							if (_MyDatabase == null) {
								oout.writeObject(DTO.CreateDTO("no Database"));
								oout.flush();
								Thread.sleep(10);
								oout.reset();
								continue;
							}

							query = new Query(_MyDatabase);

						}

						DTO dto = query.execQuery(sqlString);
						oout.writeObject(dto);

						oout.flush();
						Thread.sleep(10);
						oout.reset();
					} catch (Exception ex) {
						try {
							oout.writeObject(DTO.CreateDTO("Disconnected!"));
							oout.close();
							client.close();
						} catch (Exception e) {

						}
						System.out.println("  end.");
						break;
					}
				}
			}
		};

		playThread.start();

	}

	private void SaveDatabaseToFile() {
		if (_MyDatabase != null) {
			try {
				_outputSteam = new FileOutputStream(FILEPATH);
				_objOutputStream = new ObjectOutputStream(_outputSteam);
				_objOutputStream.writeObject(_MyDatabase);
				_objOutputStream.flush();
				_outputSteam.close();
			} catch (IOException e) {
				e.printStackTrace();
			}

			JOptionPane.showMessageDialog(new Server(), "Database saved.",
					"Infomation", JOptionPane.INFORMATION_MESSAGE);
		} else {
			JOptionPane.showMessageDialog(new Server(), "No database to save.",
					"Error", JOptionPane.ERROR_MESSAGE);
		}
	}

	private void LoadDatabaseFromFile() {
		if (fileChooser.showOpenDialog(new Server()) == JFileChooser.APPROVE_OPTION) {
			File loadFile = fileChooser.getSelectedFile();
			try {
				_inputStream = new FileInputStream(loadFile.getPath());
				ObjectInputStream reader = new ObjectInputStream(_inputStream);
				_MyDatabase = (DataBase) reader.readObject();
				UpdateGUI();
				this.FILEPATH = loadFile.getPath();
				reader.close();
			} catch (FileNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (ClassNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

		}
	}

	public void DelDatabase() {
		if (this._MyDatabase != null) {
			if (JOptionPane.showConfirmDialog(this, "Are you sure you want to delete this database?",
					"Chu y", JOptionPane.YES_NO_OPTION) == 0) {
				File deleteFile = new File(this.FILEPATH);
				Deleting(deleteFile);
				JOptionPane.showMessageDialog(this, "Done!!!");
				this._MyDatabase = null;
				this.FILEPATH = null;
				UpdateDesignTab();
				UpdateViewTab();
				UpdateGUI();
				labelFocus.setText("No database load");
			}
		} else {
			JOptionPane.showMessageDialog(new Server(),
					"No database to delete.");
		}
	}

	private void Deleting(File file) {
		if (file.isFile()) {
			file.delete();
		} else {
			File[] list = file.listFiles();
			for (int i = 0; i < list.length; i++) {
				Deleting(list[i]);
			}
			file.delete();
		}
	}

	private void DeleteTable(String input) {
		Table table = this._MyDatabase.getTable(input);
		if (table == null) {
			JOptionPane.showMessageDialog(new Server(),
					"Choose table to delete.", "Error",
					JOptionPane.ERROR_MESSAGE);
		} else {
			if (JOptionPane.showConfirmDialog(this, "Ban co chac chan khong?",
					"Chu y", JOptionPane.YES_NO_OPTION) == 0) {
				this._MyDatabase.deleteTable(table);
				UpdateGUI();
				UpdateDesignTab();
				UpdateViewTab();
			}
		}
	}

}

class ColorRenderer extends JLabel implements TableCellRenderer {
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private int columnIndex;

	public ColorRenderer(int column) {
		this.columnIndex = column;
		setOpaque(true);
	}

	public void setColumn(int column) {
		this.columnIndex = column;
	}

	public Component getTableCellRendererComponent(JTable table, Object value,
			boolean isSelected, boolean hasFocus, int row, int column) {

		if (value != null)
			setText(value.toString());
		else
			setText("");
		if (row == table.getRowCount() - 1) {
			setBackground(java.awt.Color.cyan);
			if (column == columnIndex) {
				setBackground(java.awt.Color.pink);
			}
		} else {
			setBackground(java.awt.Color.white);
		}

		if (isSelected) {
			setBackground(table.getSelectionBackground());
			setForeground(table.getSelectionForeground());
		}
		return this;
	}

}